﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sealight.API.Framework;
using Sealight.Data;
using Sealight.API.Ioc;
using Sealight.Core.Domain;
using Sealight.Core.DataAdapter;
using Sealight.API.Security;

namespace Sealight.CoreAPI
{
   public class UserService: IUserService
    {
        #region IUserService Members

        public bool Authenticate(string username, string password)
        {
            bool authen = false;
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                throw new ArgumentNullException("Username/password cannot be null.");

            try
            {
                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion
                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                authen = repo.Authenticate(username, MD5EncryptUtil.Encrypt(password));

            }
            catch (Exception ex)
            {
                throw new Exception("Authenticate Error::" + ex.Message, ex);
            }

            return authen;
        }

        public bool MemberExists(string username)
        {
            bool exist = false;
            if (string.IsNullOrEmpty(username))
                throw new ArgumentNullException("Username cannot be null.");
            try
            {
                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion
                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                exist = repo.MemberExists(username);
            }
            catch (Exception ex)
            {
                throw new Exception("MemberExists Error::" + ex.Message, ex);
            }

            return exist;
        }

        public user AddOrUpdate(Core.DataAdapter.user user)
        {
            if(user== null)
                throw new ArgumentNullException("User Entity is NULL.");
            if (string.IsNullOrEmpty(user.user_name))
                throw new ArgumentNullException("Username cannot be null");
            if (string.IsNullOrEmpty(user.password))
                throw new ArgumentNullException("password cannot be null");
            if (string.IsNullOrEmpty(user.email_address))
                throw new ArgumentNullException("Emailaddress cannot be null");
            //persists
            #region start_unit_of_work
            IUnitOfWork uow = null;
            if (!UnitOfWork.IsStarted)
                uow = UnitOfWork.Start();
            else uow = UnitOfWork.Current;
            #endregion
            bool commitTrans = false;
            if (!uow.IsInActiveTransaction)
            {
                //if not in active transaction
                //then begin transaction and commit it later
                uow.BeginTransaction(); //start transaction
                commitTrans = true;
            }

            try
            {
                IUserRepository repoUser = IocContainer.Container().Resolve<IUserRepository>();
                IRoleRepository repoRole = IocContainer.Container().Resolve<IRoleRepository>();
                UserEntity Entity = repoUser.GetById(user.id);
                if(Entity==null)
                    Entity = new UserEntity();

                Entity.UserName = user.user_name;
                if (Entity.Password == user.password)
                {
                    Entity.Password = user.password;
                }
                else
                {
                    Entity.Password = MD5EncryptUtil.Encrypt(user.password);
                }                
                Entity.EmailAddress = user.email_address;
                Entity.LastLoginTime = user.last_login_time;               

              /*  if (user.roles != null)
                {
                    Entity.Roles = new List<RoleEntity>(); 
                    foreach (role roleAdapter in user.roles)
                    {
                        RoleEntity DataRole = repoRole.GetById(roleAdapter.id);
                        if(DataRole != null)
                            Entity.Roles.Add(DataRole);
                    }
                }
               * */

                repoUser.SaveOrUpdate(Entity);
                if (commitTrans)
                    uow.TransactionalFlush();
                user = Entity.ToDataAdapter();
            }
            catch (Exception ex)
            {
//log for net
                throw new Exception("Error saving user data. ErrMsg: " + ex.Message, ex);
            }

            return user;

        }        

        public Core.DataAdapter.user GetByUsername(string username)
        {
            UserEntity data = null;
            if (string.IsNullOrEmpty(username))
                throw new ArgumentNullException("Username cannot be null.");
            try
            {
                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion
                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                data = repo.GetByUsername(username);
            }
            catch (Exception ex)
            {
                throw new Exception("GetByUsername Error::" + ex.Message, ex);
            }

            if (data != null)
                return data.ToDataAdapter();

            return null;
        }

        public Core.DataAdapter.user GetById(Guid id)
        {
            UserEntity data = null;
            if (id==Guid.Empty)
                throw new ArgumentNullException("UserID cannot be null.");
            try
            {
                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion
                
                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                data = repo.GetById(id);
            }
            catch (Exception ex)
            {
                throw new Exception("GetById Error::" + ex.Message, ex);
            }

            if (data != null)
                return data.ToDataAdapter();

            return null;
        }

        public IList<user> GetAll()
        {
            IList<user> obj = null;
            try
            {
                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion

                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                var data = repo.GetAll();

                if (data != null)
                {
                    obj = (from c in data select c.ToDataAdapter()).ToList();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("GetAll Error::" + ex.Message, ex);
            }
            return obj;
        }

        #endregion

        #region IUserService Members


        public void Delete(user data)
        {
            if (data == null)
                throw new ArgumentNullException("User Entity is NULL.");

            try
            {
                UserEntity user = null;

                #region start_unit_of_work
                IUnitOfWork uow = null;
                if (!UnitOfWork.IsStarted)
                    uow = UnitOfWork.Start();
                else uow = UnitOfWork.Current;
                #endregion
                bool commitTrans = false;
                if (!uow.IsInActiveTransaction)
                {
                    //if not in active transaction
                    //then begin transaction and commit it later
                    uow.BeginTransaction(); //start transaction
                    commitTrans = true;
                }
                IUserRepository repo = IocContainer.Container().Resolve<IUserRepository>();
                user = repo.GetById(data.id);

                if (user != null)
                    repo.Delete(user);

                if (commitTrans)
                    uow.TransactionalFlush();

            }
            catch (Exception ex)
            {
                throw new Exception("Delete Error::" + ex.Message, ex);
            }
        }

        #endregion
    }
}
